package com.imm.da.base.vm

import androidx.lifecycle.LiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

/**
 * <p>------------------------------------------------------
 * <p> Copyright (C) 2021 zhangmz, All rights reserved.
 * <p> If there is technical discussion, you can contact zhangmz90@foxmail.com
 * <p>------------------------------------------------------
 * <p> des
 * <p>
 *
 * @author Created by Administrator
 * @date on 2021 2021/11/14 13:39
 */
open class BaseViewModel : ViewModel() {

    fun <T> request(
        result : LiveData<T>,
        query : () -> Unit
    ) : LiveData<T> {
        viewModelScope.launch {
            withContext(Dispatchers.IO){
                query()
            }
        }
        return result
    }

    /**
     * 不带参数请求
     */
    fun <T> request (
        // 请求体
        query : () -> T?,
        // 验证成功后的回调
        success : (result : T?) -> Unit,
        // 数据验证或者请求失败
        failure: (e: Throwable) -> Unit = { }
    ) {
        viewModelScope.launch {
            withContext(Dispatchers.IO){
                query()
            }?.let {
                success(it)
            }?: failure(Throwable("response can not be null"))
        }
    }
    /**
     * 不带参数请求
     */
    fun <R, T> request (
        // 请求体
        query : () -> R,
        // 数据验证
        catch : (result : R) -> T,
        // 验证成功后的回调
        success : (result : T) -> Unit,
        // 数据验证或者请求失败
        failure: (e: Throwable) -> Unit = { }
    ) {
        viewModelScope.launch {
            withContext(Dispatchers.IO){
                query()
            }.runCatching {
                catch(this)
            }.onSuccess {
                success(it)
            }.onFailure {
                failure(it)
            }
        }
    }

    /**
     * 带参请求
     */
    fun <P, R, T> request (
        // 参数
        param : P,
        // 请求体
        query : (param : P) -> R,
        // 数据验证
        catch : (result : R) -> T,
        // 验证成功后的回调
        success : (result : T) -> Unit,
        // 数据验证或者请求失败
        failure: (e: Throwable) -> Unit = { }
    ) {
        viewModelScope.launch {
            withContext(Dispatchers.IO){
                query(param)
            }.runCatching {
                catch(this)
            }.onSuccess {
                success(it)
            }.onFailure {
                failure(it)
            }
        }
    }

}